package com.example.performance.config;

import com.example.performance.model.HttpRequest;
import com.example.performance.model.LoadTestConfig;
import com.example.performance.model.TestScenario;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
 * 配置文件加载器
 * 支持YAML和JSON格式的配置文件
 */
public class ConfigLoader {

    private static final Logger logger = LoggerFactory.getLogger(ConfigLoader.class);

    private final ObjectMapper yamlMapper;
    private final ObjectMapper jsonMapper;

    public ConfigLoader() {
        this.yamlMapper = new ObjectMapper(new YAMLFactory());
        this.jsonMapper = new ObjectMapper();
    }

    /**
     * 从文件路径加载配置
     * 
     * @param configPath 配置文件路径
     * @return 加载的配置对象
     * @throws IOException 文件读取异常
     */
    public LoadTestConfig loadFromFile(String configPath) throws IOException {
        if (configPath == null || configPath.trim().isEmpty()) {
            throw new IllegalArgumentException("配置文件路径不能为空");
        }

        File configFile = new File(configPath);
        if (!configFile.exists()) {
            throw new IOException("配置文件不存在: " + configPath);
        }

        if (!configFile.canRead()) {
            throw new IOException("配置文件无法读取: " + configPath);
        }

        logger.info("加载配置文件: {}", configPath);

        try {
            LoadTestConfig config;

            // 根据文件扩展名选择解析器
            if (configPath.toLowerCase().endsWith(".yml") || configPath.toLowerCase().endsWith(".yaml")) {
                config = yamlMapper.readValue(configFile, LoadTestConfig.class);
            } else if (configPath.toLowerCase().endsWith(".json")) {
                config = jsonMapper.readValue(configFile, LoadTestConfig.class);
            } else {
                // 尝试YAML格式，如果失败再尝试JSON格式
                try {
                    config = yamlMapper.readValue(configFile, LoadTestConfig.class);
                } catch (IOException e) {
                    logger.debug("YAML解析失败，尝试JSON格式", e);
                    config = jsonMapper.readValue(configFile, LoadTestConfig.class);
                }
            }

            // 验证配置
            if (!config.isValid()) {
                throw new IllegalArgumentException("配置文件内容无效，请检查必需字段");
            }

            logger.info("配置加载成功: {}", config.getTestName());
            return config;

        } catch (IOException e) {
            logger.error("解析配置文件失败: {}", configPath, e);
            throw new IOException("解析配置文件失败: " + e.getMessage(), e);
        }
    }

    /**
     * 从classpath资源加载配置
     * 
     * @param resourcePath 资源路径
     * @return 加载的配置对象
     * @throws IOException 资源读取异常
     */
    public LoadTestConfig loadFromResource(String resourcePath) throws IOException {
        if (resourcePath == null || resourcePath.trim().isEmpty()) {
            throw new IllegalArgumentException("资源路径不能为空");
        }

        logger.info("从classpath加载配置: {}", resourcePath);

        try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(resourcePath)) {
            if (inputStream == null) {
                throw new IOException("找不到classpath资源: " + resourcePath);
            }

            LoadTestConfig config;

            // 根据文件扩展名选择解析器
            if (resourcePath.toLowerCase().endsWith(".yml") || resourcePath.toLowerCase().endsWith(".yaml")) {
                config = yamlMapper.readValue(inputStream, LoadTestConfig.class);
            } else if (resourcePath.toLowerCase().endsWith(".json")) {
                config = jsonMapper.readValue(inputStream, LoadTestConfig.class);
            } else {
                // 默认尝试YAML格式
                config = yamlMapper.readValue(inputStream, LoadTestConfig.class);
            }

            // 验证配置
            if (!config.isValid()) {
                throw new IllegalArgumentException("配置文件内容无效，请检查必需字段");
            }

            logger.info("配置加载成功: {}", config.getTestName());
            return config;

        } catch (IOException e) {
            logger.error("解析配置资源失败: {}", resourcePath, e);
            throw new IOException("解析配置资源失败: " + e.getMessage(), e);
        }
    }

    /**
     * 保存配置到文件
     * 
     * @param config     配置对象
     * @param outputPath 输出文件路径
     * @throws IOException 文件写入异常
     */
    public void saveToFile(LoadTestConfig config, String outputPath) throws IOException {
        if (config == null) {
            throw new IllegalArgumentException("配置对象不能为null");
        }
        if (outputPath == null || outputPath.trim().isEmpty()) {
            throw new IllegalArgumentException("输出路径不能为空");
        }

        logger.info("保存配置到文件: {}", outputPath);

        try {
            File outputFile = new File(outputPath);
            File parentDir = outputFile.getParentFile();
            if (parentDir != null && !parentDir.exists()) {
                if (!parentDir.mkdirs()) {
                    throw new IOException("无法创建目录: " + parentDir.getAbsolutePath());
                }
            }

            // 根据文件扩展名选择格式
            if (outputPath.toLowerCase().endsWith(".json")) {
                jsonMapper.writerWithDefaultPrettyPrinter().writeValue(outputFile, config);
            } else {
                // 默认使用YAML格式
                yamlMapper.writeValue(outputFile, config);
            }

            logger.info("配置保存成功: {}", outputPath);

        } catch (IOException e) {
            logger.error("保存配置文件失败: {}", outputPath, e);
            throw new IOException("保存配置文件失败: " + e.getMessage(), e);
        }
    }

    /**
     * 创建默认配置模板
     * 
     * @return 默认配置对象
     */
    public LoadTestConfig createDefaultConfig() {
        LoadTestConfig config = new LoadTestConfig();
        config.setTestName("示例压测");
        config.setDescription("这是一个示例压测配置");
        config.setConcurrentUsers(10);
        config.setTestDurationSeconds(60);
        config.setRampUpSeconds(5);

        // 添加默认测试场景
        TestScenario scenario = new TestScenario("示例场景", "这是一个示例测试场景");
        HttpRequest request = new HttpRequest("示例请求", "GET", "http://httpbin.org/get");
        scenario.addRequest(request);
        config.addScenario(scenario);

        return config;
    }

    /**
     * 验证配置文件格式
     * 
     * @param configPath 配置文件路径
     * @return 验证结果
     */
    public boolean validateConfigFile(String configPath) {
        try {
            LoadTestConfig config = loadFromFile(configPath);
            return config.isValid();
        } catch (Exception e) {
            logger.error("配置文件验证失败: {}", configPath, e);
            return false;
        }
    }
}